package com.game.core.res
{
	import br.com.stimuli.loading.BulkLoader;
	import br.com.stimuli.loading.loadingtypes.ImageItem;
	import br.com.stimuli.loading.loadingtypes.LoadingItem;
	
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;

	public class GameResource
	{
		public var url : String;
		internal var loadItem : LoadingItem;
		private var _notifyCompleteds : Function;
		private var _notifyIOErrors : Function;
		private var _notifyProgresses : Function;
		
		public var version : String = "0";
		private var _content : *;
		public var attr : Dictionary;
		public var _bulkProps : BulkProps = new BulkProps();
		
		public function GameResource(id:String)
		{
			_bulkProps.id = id;
			attr = new Dictionary();
		}
		
		public function get isLoaded() : Boolean
		{
			return loadItem && loadItem.status == LoadingItem.STATUS_FINISHED;
		}
		
		public function get isIoError() : Boolean
		{
			return loadItem && loadItem.status == LoadingItem.STATUS_ERROR;
		}
		
		public function get isPaused() : Boolean
		{
			return loadItem && loadItem.status == LoadingItem.STATUS_STOPPED;
		}
		
		public function get isUnload() : Boolean
		{
			return !loadItem || !loadItem.status;
		}
		
		public function get id() : String
		{
			return _bulkProps.id;
		}
		
		public function getType() : String
		{
			return !loadItem ? _bulkProps.type : loadItem.type;
		}
		
		public function getXml():XML
		{
			if(!_content)
			{
				_content = ResourceParser.getXML(this);
			}
			return _content;
		}
		
		public function getText() : String
		{
			if(!_content)
			{
				_content = ResourceParser.getTxt(this);
			}
			return _content;
		}
		
		public function getBinary(clearMemory : Boolean = true) : ByteArray
		{
			return ResourceParser.getBinary(this , clearMemory);
		}
		
		public function getClass(name : String) : Class
		{
			return (loadItem as ImageItem).getDefinitionByName(name) as Class;
		}
		
		public function getImage() : BitmapData
		{
			if(!_content)
			{
				_content = ResourceManager.getInstance().bulkLoader.getBitmapData(id , true);
			}
			return _content;
		}
		
		public function type(type : String) : GameResource
		{
			_bulkProps.type = type;
			return this;
		}
		
		public function load() : GameResource
		{
			if(isLoaded)
				_onComplete();
			else if(isIoError)
				_onIOError();
			else
				add2Bulk();
			return this;
		}
		
		private function add2Bulk():void
		{
			var bulkLoader : BulkLoader = ResourceManager.getInstance().bulkLoader;
			if(!loadItem)
			{
				loadItem = bulkLoader.add(url + '?version=' + version,_bulkProps);
				loadItem.addEventListener(Event.COMPLETE , _onComplete);
				loadItem.addEventListener(BulkLoader.ERROR , _onIOError);
				loadItem.addEventListener(ProgressEvent.PROGRESS , _onProgress);
//				_loadItem.addEventListener(SecurityErrorEvent.SECURITY_ERROR , _onSecurityError);
			}
			
			if(isPaused)
				bulkLoader.resume(id);
			
			bulkLoader.start();
		}
		
		private function cleanListener() : void
		{
			if(loadItem)
			{
				loadItem.removeEventListener(Event.COMPLETE , _onComplete);
				loadItem.removeEventListener(BulkLoader.ERROR , _onIOError);
				loadItem.removeEventListener(ProgressEvent.PROGRESS, _onProgress);
//				loadItem.removeEventListener(SecurityErrorEvent.SECURITY_ERROR , _onSecurityError);
			}
		}
		
		private function _onSecurityError(e : SecurityErrorEvent) : void
		{
			trace('安全沙箱错误:' , id , url , '加载失败' , e ? e.toString() : '');
			cleanListener();
			invokeIOError();
		}
		
		private function _onComplete(e:Event = null):void
		{
			cleanListener();
			invokeComplete();
		}
		
		private function _onIOError(e:Event = null):void
		{
			trace('GameResource加载文件:' , id + 'url:' + url + '失败！' , e ? e.toString() : '');
			cleanListener();
			invokeIOError();
		}
		
		private function _onProgress(e : ProgressEvent):void
		{
			if(_notifyProgresses != null)
			{
				var progress : ProgressInfo = ProgressInfo.PROGRESS;			
				progress.bytesLoaded = e.bytesLoaded;
				progress.bytesTotal = e.bytesTotal;
				progress.bytesTotalCurrent = 0;
				progress.itemsLoaded = 0;
				progress.itemsTotal = 1;
				progress.weightPercent = 0;
				progress.url = url;
				progress.name = id;
				invokeProgress(e);
			}
		}
		
		private function invokeComplete() : void
		{
			if(_notifyCompleteds != null)
				_notifyCompleteds(this);
		}
		
		private function invokeIOError() : void
		{
			if(_notifyIOErrors != null)
				_notifyIOErrors(this);
		}
		
		private function invokeProgress(progress : ProgressEvent) : void
		{
			if(_notifyProgresses != null)
				_notifyProgresses(progress);
		}
		
		public function onComplete(notifyCompleted : Function) : GameResource
		{
			_notifyCompleteds = notifyCompleted;
			return this;
		}
		
		public function onIOError(notifyIOError : Function) : GameResource
		{
			_notifyIOErrors = notifyIOError;
			return this;
		}
		
		public function onProgress(notifyProgress : Function) : GameResource
		{
			_notifyProgresses = notifyProgress;
			return this;
		}
		
		/**
		 * 清除帧听的回调
		 */
		private function cleanNotify() : void
		{
			_notifyCompleteds = null;
			_notifyIOErrors = null;
			_notifyProgresses = null;
		}
		
		public function pause() : void
		{
			if(loadItem && loadItem.status != LoadingItem.STATUS_FINISHED)
			{
				var bulkLoader : BulkLoader = ResourceManager.getInstance().bulkLoader;
				bulkLoader.pause(id , true);
			}
		}
		
		public function unload() : void
		{
			pause();
			if(isIoError)
			{//如果出现IO错误，从BulkLoader中删除
				ResourceManager.getInstance().bulkLoader.remove(id , true);
			}
			
			cleanListener();
			cleanNotify();
			_content = null;
			loadItem = null;
			attr = null;
			
			ResourceManager.getInstance().bulkLoader.getContent(id , true);
			ResourceManager.getInstance().clearResource(id);
		}
		
	}
}